package com.breeze.components.message.secure.config;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.breeze.components.message.secure.SecureInvokeAspect;
import com.breeze.components.message.secure.SecureInvokeService;
import com.breeze.components.message.secure.record.SecureInvokeRecordMapper;
import com.breeze.components.message.secure.record.SecureInvokeRecordService;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.util.function.SingletonSupplier;

/**
 * 自动装配类
 *
 * @author breeze
 */
@AutoConfiguration
@EnableScheduling
@MapperScan(basePackageClasses = SecureInvokeRecordMapper.class)
@Import({SecureInvokeAspect.class, SecureInvokeRecordService.class})
public class SecureInvokeAutoConfiguration {

  protected Executor executor;

  @Autowired
  void setConfigurers(ObjectProvider<SecureInvokeConfigurer> configurers) {
    Supplier<SecureInvokeConfigurer> configurer =
        SingletonSupplier.of(
            () -> {
              List<SecureInvokeConfigurer> candidates =
                  configurers.stream().collect(Collectors.toList());
              if (CollUtil.isEmpty(candidates)) {
                return null;
              }
              Assert.isFalse(candidates.size() > 1, "Only one SecureInvokeConfigurer may exist");
              return candidates.getFirst();
            });
    executor =
        Optional.ofNullable(configurer.get())
            .map(SecureInvokeConfigurer::getSecureInvokeExecutor)
            .orElse(ForkJoinPool.commonPool());
  }

  @Bean
  public SecureInvokeService getSecureInvokeService(
      SecureInvokeRecordService secureInvokeRecordService) {
    return new SecureInvokeService(secureInvokeRecordService, executor);
  }
}
